//
//  NSFileManagerAdditions.m
//  Tint
//
//  Created by Kevin Wu on 3/12/12.
//  Copyright (c) 2012 Telligenty. All rights reserved.
//

#import "NSFileManagerAdditions.h"
#import "TTCore.h"



typedef enum {
    TTFileManagerItemTypeFile = 1UL<<0, 
    TTFileManagerItemTypeDirectory = 1UL<<1
} TTFileManagerItemType;

typedef enum {
    TTFileManagerResultTypeName = 0, 
    TTFileManagerResultTypeRelativePath, 
    TTFileManagerResultTypeAbsolutePath
} TTFileManagerResultType;


@interface NSFileManager (TintPrivate)

/*
 * Basic implementation
 */
- (NSArray *)itemsInFolder:(NSString *)path itemType:(TTFileManagerItemType)itemType resultType:(TTFileManagerResultType)resultType;
- (NSArray *)allItemsInFolder:(NSString *)path itemType:(TTFileManagerItemType)itemType resultType:(TTFileManagerResultType)resultType;

- (NSArray *)filesMatchingExtension:(NSString *)extension inFolder:(NSString *)path resultType:(TTFileManagerResultType)resultType;
- (NSArray *)allFilesMatchingExtension:(NSString *)extension inFolder:(NSString *)path resultType:(TTFileManagerResultType)resultType;

@end


@implementation NSFileManager (TintPrivate)

#pragma mark - Basic implementation

- (NSArray *)itemsInFolder:(NSString *)path itemType:(TTFileManagerItemType)itemType resultType:(TTFileManagerResultType)resultType {
    if (!TTIsStringWithText(path))
        return nil;
    
    
    NSMutableArray *results = [NSMutableArray array];
    
    NSError *error = nil;
    NSArray *contents = [self contentsOfDirectoryAtPath:path error:&error];
    if (error == nil) {
        
        for (NSString *file in contents) {
            
            // Ignore hidden file
            if ([file hasPrefix:@"."])
                continue;
            
            
            NSString *filePath = [path stringByAppendingPathComponent:file];
            
            BOOL isDirectory = NO;
            [self fileExistsAtPath:filePath isDirectory:&isDirectory];
            
            if (isDirectory) {
                
                if (itemType & TTFileManagerItemTypeDirectory) {
                    
                    if (resultType == TTFileManagerResultTypeName) {
                        [results addObject:[filePath lastPathComponent]];
                    } else if (resultType == TTFileManagerResultTypeRelativePath) {
                        [results addObject:file];
                    } else if (resultType == TTFileManagerResultTypeAbsolutePath) {
                        [results addObject:filePath];
                    }
                    
                }
                
            } else {
                
                if (itemType & TTFileManagerItemTypeFile) {
                    
                    if (resultType == TTFileManagerResultTypeName) {
                        [results addObject:[filePath lastPathComponent]];
                    } else if (resultType == TTFileManagerResultTypeRelativePath) {
                        [results addObject:file];
                    } else if (resultType == TTFileManagerResultTypeAbsolutePath) {
                        [results addObject:filePath];
                    }
                    
                }
                
            }
            
        }
        
        if (TTIsArrayWithItems(results)) {
            return results;
        }
        
    }
    
    return nil;
}

- (NSArray *)allItemsInFolder:(NSString *)path itemType:(TTFileManagerItemType)itemType resultType:(TTFileManagerResultType)resultType {
    
    NSMutableArray *results = [NSMutableArray array];
    
    NSDirectoryEnumerator *enumerator = [self enumeratorAtPath:path];
    NSString *file = nil;
    
    while ((file = [enumerator nextObject])) {
        
        // Ignore hidden file
        if ([file hasPrefix:@"."])
            continue;
        
        NSString *filePath = [path stringByAppendingPathComponent:file];
        
        BOOL isDirectory = NO;
        [self fileExistsAtPath:filePath isDirectory:&isDirectory];
        
        if (isDirectory) {
            
            if (itemType & TTFileManagerItemTypeDirectory) {
                
                if (resultType == TTFileManagerResultTypeName) {
                    [results addObject:[filePath lastPathComponent]];
                } else if (resultType == TTFileManagerResultTypeRelativePath) {
                    [results addObject:file];
                } else if (resultType == TTFileManagerResultTypeAbsolutePath) {
                    [results addObject:filePath];
                }
                
            }
            
        } else {
            
            if (itemType & TTFileManagerItemTypeFile) {
                
                if (resultType == TTFileManagerResultTypeName) {
                    [results addObject:[filePath lastPathComponent]];
                } else if (resultType == TTFileManagerResultTypeRelativePath) {
                    [results addObject:file];
                } else if (resultType == TTFileManagerResultTypeAbsolutePath) {
                    [results addObject:filePath];
                }
                
            }
            
        }
        
    }
    
    if (TTIsArrayWithItems(results)) {
        return results;
    }
    
    return nil;
}


- (NSArray *)filesMatchingExtension:(NSString *)extension inFolder:(NSString *)path resultType:(TTFileManagerResultType)resultType {
    if (!TTIsStringWithText(path) || !TTIsStringWithText(extension))
        return nil;
    
    
    NSMutableArray *results = [NSMutableArray array];
    
    NSError *error = nil;
    NSArray *contents = [self contentsOfDirectoryAtPath:path error:&error];
    if (error == nil) {
        
        for (NSString *file in contents) {
            
            // Ignore hidden file
            if ([file hasPrefix:@"."])
                continue;
            
            
            NSString *filePath = [path stringByAppendingPathComponent:file];
            
            if (![[filePath pathExtension] isEqualToString:extension])
                continue;
            
            BOOL isDirectory = NO;
            [self fileExistsAtPath:filePath isDirectory:&isDirectory];
            
            if (!isDirectory) {
                
                if (resultType == TTFileManagerResultTypeName) {
                    [results addObject:[filePath lastPathComponent]];
                } else if (resultType == TTFileManagerResultTypeRelativePath) {
                    [results addObject:file];
                } else if (resultType == TTFileManagerResultTypeAbsolutePath) {
                    [results addObject:filePath];
                }
                
            }
            
        }
        
        if (TTIsArrayWithItems(results)) {
            return results;
        }
        
    }
    
    return nil;
}

- (NSArray *)allFilesMatchingExtension:(NSString *)extension inFolder:(NSString *)path resultType:(TTFileManagerResultType)resultType {
    
    NSMutableArray *results = [NSMutableArray array];
    
    NSDirectoryEnumerator *enumerator = [self enumeratorAtPath:path];
    NSString *file = nil;
    
    while ((file = [enumerator nextObject])) {
        
        // Ignore hidden file
        if ([file hasPrefix:@"."])
            continue;
        
        NSString *filePath = [path stringByAppendingPathComponent:file];
        
        if (![[filePath pathExtension] isEqualToString:extension])
            continue;
        
        BOOL isDirectory = NO;
        [self fileExistsAtPath:filePath isDirectory:&isDirectory];
        
        if (!isDirectory) {
            
            if (resultType == TTFileManagerResultTypeName) {
                [results addObject:[filePath lastPathComponent]];
            } else if (resultType == TTFileManagerResultTypeRelativePath) {
                [results addObject:file];
            } else if (resultType == TTFileManagerResultTypeAbsolutePath) {
                [results addObject:filePath];
            }
            
        }
        
    }
    
    if (TTIsArrayWithItems(results)) {
        return results;
    }
    
    return nil;
    
}

@end





@implementation NSFileManager (Tint)



#pragma mark - Shallow enumerate

- (NSArray *)fileNamesInFolder:(NSString *)path {
    return [self itemsInFolder:path 
                      itemType:TTFileManagerItemTypeFile 
                    resultType:TTFileManagerResultTypeName];
}
- (NSArray *)fileRelativePathsInFolder:(NSString *)path {
    return [self itemsInFolder:path 
                      itemType:TTFileManagerItemTypeFile 
                    resultType:TTFileManagerResultTypeRelativePath];
}
- (NSArray *)fileAbsolutePathsInFolder:(NSString *)path {
    return [self itemsInFolder:path 
                      itemType:TTFileManagerItemTypeFile 
                    resultType:TTFileManagerResultTypeAbsolutePath];
}

- (NSArray *)directoryNamesInFolder:(NSString *)path {
    return [self itemsInFolder:path 
                      itemType:TTFileManagerItemTypeDirectory 
                    resultType:TTFileManagerResultTypeName];
}
- (NSArray *)directoryRelativePathsInFolder:(NSString *)path {
    return [self itemsInFolder:path 
                      itemType:TTFileManagerItemTypeDirectory 
                    resultType:TTFileManagerResultTypeRelativePath];
}
- (NSArray *)directoryAbsolutePathsInFolder:(NSString *)path {
    return [self itemsInFolder:path 
                      itemType:TTFileManagerItemTypeDirectory 
                    resultType:TTFileManagerResultTypeAbsolutePath];
}

- (NSArray *)itemNamesInFolder:(NSString *)path {
    return [self itemsInFolder:path 
                      itemType:TTFileManagerItemTypeFile | TTFileManagerItemTypeDirectory 
                    resultType:TTFileManagerResultTypeName];
}
- (NSArray *)itemRelativePathsInFolder:(NSString *)path {
    return [self itemsInFolder:path 
                      itemType:TTFileManagerItemTypeFile | TTFileManagerItemTypeDirectory 
                    resultType:TTFileManagerResultTypeRelativePath];
}
- (NSArray *)itemAbsolutePathsInFolder:(NSString *)path {
    return [self itemsInFolder:path 
                      itemType:TTFileManagerItemTypeFile | TTFileManagerItemTypeDirectory 
                    resultType:TTFileManagerResultTypeAbsolutePath];
}

- (NSArray *)fileNamesMatchingExtension:(NSString *)extension inFolder:(NSString *)path {
    return [self filesMatchingExtension:extension 
                               inFolder:path 
                             resultType:TTFileManagerResultTypeName];
}
- (NSArray *)fileRelativePathsMatchingExtension:(NSString *)extension inFolder:(NSString *)path {
    return [self filesMatchingExtension:extension 
                               inFolder:path 
                             resultType:TTFileManagerResultTypeRelativePath];
}
- (NSArray *)fileAbsolutePathsMatchingExtension:(NSString *)extension inFolder:(NSString *)path {
    return [self filesMatchingExtension:extension 
                               inFolder:path 
                             resultType:TTFileManagerResultTypeAbsolutePath];
}



#pragma mark - Deep enumerate

- (NSArray *)allFileNamesInFolder:(NSString *)path {
    return [self allItemsInFolder:path 
                         itemType:TTFileManagerItemTypeFile 
                       resultType:TTFileManagerResultTypeName];
}
- (NSArray *)allFileRelativePathsInFolder:(NSString *)path {
    return [self allItemsInFolder:path 
                         itemType:TTFileManagerItemTypeFile 
                       resultType:TTFileManagerResultTypeRelativePath];
}
- (NSArray *)allFileAbsolutePathsInFolder:(NSString *)path {
    return [self allItemsInFolder:path 
                         itemType:TTFileManagerItemTypeFile 
                       resultType:TTFileManagerResultTypeAbsolutePath];
}

- (NSArray *)allDirectoryNamesInFolder:(NSString *)path {
    return [self allItemsInFolder:path 
                         itemType:TTFileManagerItemTypeDirectory 
                       resultType:TTFileManagerResultTypeName];
}
- (NSArray *)allDirectoryRelativePathsInFolder:(NSString *)path {
    return [self allItemsInFolder:path 
                         itemType:TTFileManagerItemTypeDirectory 
                       resultType:TTFileManagerResultTypeRelativePath];
}
- (NSArray *)allDirectoryAbsolutePathsInFolder:(NSString *)path {
    return [self allItemsInFolder:path 
                         itemType:TTFileManagerItemTypeDirectory 
                       resultType:TTFileManagerResultTypeAbsolutePath];
}

- (NSArray *)allItemNamesInFolder:(NSString *)path {
    return [self allItemsInFolder:path 
                         itemType:TTFileManagerItemTypeFile | TTFileManagerItemTypeDirectory 
                       resultType:TTFileManagerResultTypeName];
}
- (NSArray *)allItemRelativePathsInFolder:(NSString *)path {
    return [self allItemsInFolder:path 
                         itemType:TTFileManagerItemTypeFile | TTFileManagerItemTypeDirectory 
                       resultType:TTFileManagerResultTypeRelativePath];
}
- (NSArray *)allItemAbsolutePathsInFolder:(NSString *)path {
    return [self allItemsInFolder:path 
                         itemType:TTFileManagerItemTypeFile | TTFileManagerItemTypeDirectory 
                       resultType:TTFileManagerResultTypeAbsolutePath];
}

- (NSArray *)allFileNamesMatchingExtension:(NSString *)extension inFolder:(NSString *)path {
    return [self allFilesMatchingExtension:extension 
                                  inFolder:path 
                                resultType:TTFileManagerResultTypeName];
}
- (NSArray *)allFileRelativePathsMatchingExtension:(NSString *)extension inFolder:(NSString *)path {
    return [self allFilesMatchingExtension:extension 
                                  inFolder:path 
                                resultType:TTFileManagerResultTypeRelativePath];
}
- (NSArray *)allFileAbsolutePathsMatchingExtension:(NSString *)extension inFolder:(NSString *)path {
    return [self allFilesMatchingExtension:extension 
                                  inFolder:path 
                                resultType:TTFileManagerResultTypeAbsolutePath];
}

@end
